﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTO;
using DAL;

namespace BLL.Article
{
    public class Article : BaseArticle
    {
        #region "Constructors"
        public Article(int id, DateTime addedDate, string addedBy,
           int categoryID, string title, string artabstract,
           string body, DateTime releaseDate, DateTime expireDate, bool approved,
           bool listed, bool commentsEnabled, bool onlyForMembers,
           int viewCount, int votes, int totalRating, string imageUrl)
        {
            this.ID = id;
            this.AddedDate = addedDate;
            this.AddedBy = addedBy;
            this.CategoryID = categoryID;
            this.Title = title;
            this.Abstract = artabstract;
            this.Body = body;
            this.ReleaseDate = releaseDate;
            this.ExpireDate = expireDate;
            this.Approved = approved;
            this.Listed = listed;
            this.CommentsEnabled = commentsEnabled;
            this.OnlyForMembers = onlyForMembers;
            this.ViewCount = viewCount;
            this.Votes = votes;
            this.TotalRating = totalRating;
            this.ImageUrl = imageUrl;
        }

        #endregion

        #region "Public Properties"

        public int CategoryID { get; set; }

        //public string CategoryTitle { get; set; }

        public string Title { get; set; }

        public string Abstract { get; set; }

        public string Body { get; set; }

        public DateTime ReleaseDate { get; set; }

        public DateTime ExpireDate { get; set; }

        public bool Approved { get; set; }

        public bool Listed { get; set; }

        public bool CommentsEnabled { get; set; }

        public bool OnlyForMembers { get; set; }

        public int ViewCount { get; set; }

        public int Votes { get; set; }

        public int TotalRating { get; set; }

        public string ImageUrl { get; set; }

        public bool IsNew
        {
            get
            {
                double distance = (DateTime.Now.Subtract(ReleaseDate)).TotalDays;
                return (distance <= 30);
            }

        }

        public bool IsShowImage
        {
            get
            {
                if (ImageUrl == "")
                    return false;
                else
                    return true;
            }

        }

        #endregion

        #region Get From ArticleDetail
        /// <summary>
        /// Returns a Article object filled with the data taken from the input ArticleDetails
        /// </summary>
        private static Article GetArticleFromArticleDetails(ArticleDetails record)
        {
            if (record == null)
                return null;
            else
            {
                return new Article(record.ID, record.AddedDate, record.AddedBy,
                   record.CategoryID, record.Title, record.Abstract, record.Body,
                   record.ReleaseDate, record.ExpireDate,
                   record.Approved, record.Listed, record.CommentsEnabled, record.OnlyForMembers,
                   record.ViewCount, record.Votes, record.TotalRating, record.ImageUrl);
            }
        }

        /// <summary>
        /// Returns a list of Article objects filled with the data taken from the input list of ArticleDetails
        /// </summary>
        private static List<Article> GetArticleListFromArticleDetailsList(List<ArticleDetails> recordset)
        {
            List<Article> articles = new List<Article>();
            foreach (ArticleDetails record in recordset)
                articles.Add(GetArticleFromArticleDetails(record));
            return articles;
        }

        #endregion

        #region Static Method
        /// <summary>
        /// Returns a collection with all articles
        /// </summary>
        public static List<Article> ListArticles()
        {
            return ListArticles(0, BizObject.MAXROWS);
        }
        public static List<Article> ListArticles(int startRowIndex, int maximumRows)
        {
            List<Article> articles = null;
            string key = "Articles_Articles_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articles = (List<Article>)BizObject.Cache[key];
            }
            else
            {
                List<ArticleDetails> recordset = SiteProvider.Articles.ListArticles(
                   GetPageIndex(startRowIndex, maximumRows), maximumRows);
                articles = GetArticleListFromArticleDetailsList(recordset);
                BaseArticle.CacheData(key, articles);
            }
            return articles;
        }

        /// <summary>
        /// Returns a collection with all articles for the specified category
        /// </summary>
        public static List<Article> ListArticles(int categoryID)
        {
            return ListArticles(categoryID, 0, BizObject.MAXROWS);
        }
        public static List<Article> ListNewArticles()
        {
            return ListArticles(1,0,5);
        }
        public static List<Article> ListNewArticlesByArticleID(int articleID)
        {
            int categoryID = GetArticleByID(articleID).CategoryID;
            return ListArticles(categoryID, 0, 5);
        }
        public static List<Article> ListArticles(int categoryID, int startRowIndex, int maximumRows)
        {
            if (categoryID <= 0)
                return ListArticles(startRowIndex, maximumRows);

            List<Article> articles = null;
            string key = "Articles_Articles_" + categoryID.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articles = (List<Article>)BizObject.Cache[key];
            }
            else
            {
                List<ArticleDetails> recordset = SiteProvider.Articles.ListArticles(categoryID,
                   GetPageIndex(startRowIndex, maximumRows), maximumRows);
                articles = GetArticleListFromArticleDetailsList(recordset);
                BaseArticle.CacheData(key, articles);
            }
            return articles;
        }

        /// <summary>
        /// Returns the number of total articles
        /// </summary>
        public static int GetArticleCount()
        {
            int articleCount = 0;
            string key = "Articles_ArticleCount";

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articleCount = (int)BizObject.Cache[key];
            }
            else
            {
                articleCount = SiteProvider.Articles.GetArticleCount();
                BaseArticle.CacheData(key, articleCount);
            }
            return articleCount;
        }

        /// <summary>
        /// Returns the number of total articles for the specified category
        /// </summary>
        public static int GetArticleCount(int categoryID)
        {
            if (categoryID <= 0)
                return GetArticleCount();

            int articleCount = 0;
            string key = "Articles_ArticleCount_" + categoryID.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articleCount = (int)BizObject.Cache[key];
            }
            else
            {
                articleCount = SiteProvider.Articles.GetArticleCount(categoryID);
                BaseArticle.CacheData(key, articleCount);
            }
            return articleCount;
        }

        /// <summary>
        /// Returns a collection with all published articles
        /// </summary>
        public static List<Article> ListArticles(bool publishedOnly)
        {
            return ListArticles(publishedOnly, 0, BizObject.MAXROWS);
        }
        public static List<Article> ListArticles(bool publishedOnly, int startRowIndex, int maximumRows)
        {
            if (!publishedOnly)
                return ListArticles(startRowIndex, maximumRows);

            List<Article> articles = null;
            string key = "Articles_Articles_" + publishedOnly.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articles = (List<Article>)BizObject.Cache[key];
            }
            else
            {
                List<ArticleDetails> recordset = SiteProvider.Articles.ListPublishedArticles(DateTime.Now,
                   GetPageIndex(startRowIndex, maximumRows), maximumRows);
                articles = GetArticleListFromArticleDetailsList(recordset);
                BaseArticle.CacheData(key, articles);
            }
            return articles;
        }

        /// <summary>
        /// Returns a collection with all published articles for the specified category
        /// </summary>
        public static List<Article> ListArticles(bool publishedOnly, int categoryID)
        {
            return ListArticles(publishedOnly, categoryID, 0, BizObject.MAXROWS);
        }
        public static List<Article> ListArticles(bool publishedOnly, int categoryID, int startRowIndex, int maximumRows)
        {
            if (!publishedOnly)
                return ListArticles(categoryID, startRowIndex, maximumRows);

            if (categoryID <= 0)
                return ListArticles(publishedOnly, startRowIndex, maximumRows);

            List<Article> articles = null;
            string key = "Articles_Articles_" + publishedOnly.ToString() + "_" + categoryID.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articles = (List<Article>)BizObject.Cache[key];
            }
            else
            {
                List<ArticleDetails> recordset = SiteProvider.Articles.ListPublishedArticles(
                   categoryID, DateTime.Now,
                   GetPageIndex(startRowIndex, maximumRows), maximumRows);
                articles = GetArticleListFromArticleDetailsList(recordset);
                BaseArticle.CacheData(key, articles);
            }
            return articles;
        }

        /// <summary>
        /// Returns the number of total published articles
        /// </summary>
        public static int GetArticleCount(bool publishedOnly)
        {
            if (publishedOnly)
                return GetArticleCount();

            int articleCount = 0;
            string key = "Articles_ArticleCount_" + publishedOnly.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articleCount = (int)BizObject.Cache[key];
            }
            else
            {
                articleCount = SiteProvider.Articles.GetPublishedArticleCount(DateTime.Now);
                BaseArticle.CacheData(key, articleCount);
            }
            return articleCount;
        }

        /// <summary>
        /// Returns the number of total published articles for the specified category
        /// </summary>
        public static int GetArticleCount(bool publishedOnly, int categoryID)
        {
            if (!publishedOnly)
                return GetArticleCount(categoryID);

            if (categoryID <= 0)
                return GetArticleCount(publishedOnly);

            int articleCount = 0;
            string key = "Articles_ArticleCount_" + publishedOnly.ToString() + "_" + categoryID.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                articleCount = (int)BizObject.Cache[key];
            }
            else
            {
                articleCount = SiteProvider.Articles.GetPublishedArticleCount(categoryID, DateTime.Now);
                BaseArticle.CacheData(key, articleCount);
            }
            return articleCount;
        }

        /// <summary>
        /// Returns an Article object with the specified ID
        /// </summary>
        public static Article GetArticleByID(int articleID)
        {
            Article article = null;
            string key = "Articles_Article_" + articleID.ToString();

            if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                article = (Article)BizObject.Cache[key];
            }
            else
            {
                article = GetArticleFromArticleDetails(SiteProvider.Articles.GetArticleByID(articleID));
                BaseArticle.CacheData(key, article);
            }
            return article;
        }

        /// <summary>
        /// Updates an existing article
        /// </summary>
        public static bool UpdateArticle(int id, int categoryID, string title,
           string Abstract, string body, DateTime releaseDate, DateTime expireDate, bool approved, bool listed,
              bool commentsEnabled, bool onlyForMembers, string imageUrl)
        {
            title = BizObject.ConvertNullToEmptyString(title);
            Abstract = BizObject.ConvertNullToEmptyString(Abstract);
            body = BizObject.ConvertNullToEmptyString(body);
            imageUrl = BizObject.ConvertNullToEmptyString(imageUrl);


            if (releaseDate == DateTime.MinValue)
                releaseDate = DateTime.Now;
            if (expireDate == DateTime.MinValue)
                expireDate = DateTime.MaxValue;

            ArticleDetails record = new ArticleDetails(id, DateTime.Now, "",categoryID
               , title, Abstract, body, releaseDate, expireDate,
               true, true, true, true, 0, 0, 0, imageUrl);
            bool ret = SiteProvider.Articles.UpdateArticle(record);

            BizObject.PurgeCacheItems("articles_article_" + id.ToString());
            BizObject.PurgeCacheItems("Articles");
            return ret;
        }

        /// <summary>
        /// Creates a new article
        /// </summary>
        public static int InsertArticle(int categoryID, string title, string Abstract,
           string body, DateTime releaseDate, DateTime expireDate,
           bool approved, bool listed, bool commentsEnabled, bool onlyForMembers, string imageUrl)
        {
            // ensure that the "approved" option is false if the current user is not
            // an administrator or a editor (it may be a contributor for example)
            bool canApprove = (BizObject.CurrentUser.IsInRole("Administrators") || BizObject.CurrentUser.IsInRole("Editors"));
            if (!canApprove)
                approved = false;

            title = BizObject.ConvertNullToEmptyString(title);
            Abstract = BizObject.ConvertNullToEmptyString(Abstract);
            body = BizObject.ConvertNullToEmptyString(body);
            imageUrl = BizObject.ConvertNullToEmptyString(imageUrl);


            if (releaseDate == DateTime.MinValue)
                releaseDate = DateTime.Now;
            if (expireDate == DateTime.MinValue)
                expireDate = DateTime.MaxValue;

            ArticleDetails record = new ArticleDetails(0, DateTime.Now, BizObject.CurrentUserName,
               categoryID, title, Abstract, body, releaseDate, expireDate,
               true, true, true, true, 0, 0, 0, imageUrl);
            int ret = SiteProvider.Articles.InsertArticle(record);

            BizObject.PurgeCacheItems("articles_article");
            return ret;
        }

        /// <summary>
        /// Deletes an existing article
        /// </summary>
        public static bool DeleteArticle(int id)
        {
            bool ret = SiteProvider.Articles.DeleteArticle(id);
            BizObject.PurgeCacheItems("articles_article");
            return ret;
        }

        /// <summary>
        /// Approves an existing article
        /// </summary>
        public static bool ApproveArticle(int id)
        {
            bool ret = SiteProvider.Articles.ApproveArticle(id);
            BizObject.PurgeCacheItems("articles_article_" + id.ToString());
            BizObject.PurgeCacheItems("articles_articles");
            return ret;
        }

        /// <summary>
        /// Increments an article's view count
        /// </summary>
        public static bool IncrementArticleViewCount(int id)
        {
            return SiteProvider.Articles.IncrementArticleViewCount(id);
        }

        /// <summary>
        /// Increments an article's view count
        /// </summary>
        public static bool RateArticle(int id, int rating)
        {
            return SiteProvider.Articles.RateArticle(id, rating);
        }

        #endregion

        #region Method
        public bool Delete()
        {
            bool success = Article.DeleteArticle(this.ID);
            if (success)
                this.ID = 0;
            return success;
        }

        public bool Update()
        {
            return Article.UpdateArticle(this.ID, this.CategoryID, this.Title,
               this.Abstract, this.Body, this.ReleaseDate, this.ExpireDate, this.Approved, this.Listed,
               this.CommentsEnabled, this.OnlyForMembers, this.ImageUrl);
        }

        public bool Approve()
        {
            bool success = Article.ApproveArticle(this.ID);
            if (success)
                this.Approved = true;
            return success;
        }

        public bool IncrementViewCount()
        {
            return Article.IncrementArticleViewCount(this.ID);
        }

        public bool Rate(int rating)
        {
            return Article.RateArticle(this.ID, rating);
        }

        #endregion
    }
}
